/**
 * @desc
 *
 * @使用场景
 *
 * @author  杨晓东[of1081]
 * @company qianmi.com
 * @Date    16/4/6
 **/
'use strict';


var webpack = require('webpack');
var co =require('co');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var fse =require('fs-extra');
var fs  =require('fs');

var basicConfigFactory =require('./webpack.config.factory')();
var widgetCompileUtil  = require('../util/widget-compile-util');
let path  =require('path');
var SvgPlugin = require('./plugins/svg-plugin');

console.log('清空barBuild 文件夹下的文件..');

/**
 * 打包组件 .(带 -p文件的单位)
 * @param workBench
 * @param isProd
 */
module.exports=({workBench,env,watchMode})=>{
    let isProd = env === 'prod';
    fse.emptyDirSync(path.join(workBench,'./dist/barBuild'));
//把组件条的数量等信息统计出来;;
    let  {includeWidgetPath,templatePathList}= require( path.join(workBench,'./x-config.js'));

    co((function * (){

        //收集要打包的组件信息
        let widgetMap;
        if(watchMode){
            widgetMap = yield widgetCompileUtil.collectWidgetInfo({
                workBenchPath: workBench,
                templatePathArray: templatePathList,
                includeDirs:includeWidgetPath,
                envCode:env
            });
        } else {
            widgetMap = yield widgetCompileUtil.collectWidgetInfo({
                workBenchPath: workBench,
                includeDirs:includeWidgetPath,
                envCode:env
            });
        }
        console.log('要打包的组件索引  widgetMap',widgetMap);

        try{
            yield webpackWidget({widgetMap,isProd,workBench,env,watchMode});
        }catch(err){
            console.log(err);
        }
    })()).then(()=>{
    },(err)=>{
        console.log(err);
    });
};

function  webpackWidget({widgetMap,isProd,workBench,env,watchMode}){


    return new Promise((resolve,reject)=>{

        let entry = {};
        for(let widgetNameSpace in widgetMap){
            let item =  widgetMap[widgetNameSpace];
            let widgetCompileName  = item.widgetName+Math.random();
            let widgetPCompileName  = item.widgetName+"-p"+Math.random();

            entry[widgetCompileName] = path.join('..',item.widgetPath);
            entry[widgetPCompileName] = path.join('..',item.widgetPath+"-p");
            widgetMap[widgetNameSpace].jsFilePath ='bundle-'+widgetCompileName+'.js';
            widgetMap[widgetNameSpace].cssFilePath =widgetCompileName+'-styles.css';
            widgetMap[widgetNameSpace].jsProxyFilePath ='bundle-'+widgetPCompileName+'.js';
        }

        let plugins = [];
        if(isProd){
            plugins = [
                new webpack.DefinePlugin({
                    'process.env.NODE_ENV': JSON.stringify('production')
                }),
                new webpack.optimize.OccurrenceOrderPlugin(),
                new webpack.optimize.UglifyJsPlugin({
                    compress: {
                        warnings: false
                    }
                })
            ]
        }


        var _pp = path.join(__dirname,'./loaders/widget-loader');



        var devConfig =basicConfigFactory.buildConfig({
            entry,
            output: {
                path: path.join(workBench, './dist/barBuild'),
                filename: 'bundle-[name].js',
                chunkFilename:'chunk.[id].[name].[hash].js',
            },
            module: {
                preLoaders:[
                    {
                        test: /\.js$/, exclude: /node_modules/, loader:_pp,
                        query: {
                            // widgetMap: widgetMap,
                            workBench
                        }
                    },
                ]
            },
            plugins: [
                new ExtractTextPlugin("[name]-styles.css"),
                new SvgPlugin()
            ].concat(plugins)
        });

        var compiler = webpack(devConfig);

        if(watchMode){
            compiler.watch({
                aggregateTimeout: 1000, // wait so long for more changes
                poll: true // use polling instead of native watchers
                // pass a number to set the polling interval
            }, function(err, stats) {
                if(err){
                    console.error(err);
                }else{
                    if(stats.compilation.errors.length>0){
                        throw stats.compilation.errors;
                    }
                    co((function * (){
                        try{
                            yield compiledDeal(widgetMap,{workBench,env,watchMode});
                            resolve();
                        }catch(err){
                            reject();
                        }
                    })());
                }
            });
        }else {
            compiler.run(function(err, stats) {
                if (err) {
                    console.error(err);
                    reject(err);
                } else {
                    let compileError = stats.compilation.errors;
                    if (compileError && compileError.length>0) {
                        console.error(compileError[0].message);
                        throw new Error('打包出现错误!!!');
                        //
                        // for (let i = 0; i < compileError.length; i++) {
                        // }
                    }
                    co((function * (){
                        try{
                            yield compiledDeal(widgetMap,{workBench,env,watchMode});
                            resolve();
                        }catch(err){
                            reject();
                        }
                    })());
                }
            });
        }

    });
}


/**
 * webpack打包后后续的处理.
 * @param widgetMap
 * @param workBench
 */
function * compiledDeal(widgetMap, {workBench,env,watchMode}) {
    let _widgetMap = {};
    for (let ns in widgetMap) {
        _widgetMap[ns] = Object.assign({}, widgetMap[ns]);
    }

    for (let ns  in _widgetMap) {
        let widgetInfo = _widgetMap[ns];
        yield mvFile(widgetInfo, {workBench,watchMode,env});
    }

    //增量的去做..
    let JsonPath = path.join(workBench, './dist', 'barIndex.json');
    let barIndex = {};
    try {
        let barIndex = fse.readJsonSync(JsonPath);
    } catch (err) {
        console.warn(err);
    }

    for(let key in _widgetMap){
        barIndex[key] = _widgetMap[key]
    }

    fse.outputJsonSync(JsonPath, barIndex);
    if (watchMode) {
        console.log('bar 变了,模板再打下包. ,执行命令npm run buildTpl');
        yield _execCmd({cwd: workBench, command: 'node ./node_modules/@qianmi/x-site-tpl-develop/bin/build-tpl -e '+env });
    }
}

/**
 * 执行命令
 * @param cwd
 * @param command
 * @return {Promise}
 * @private
 */
function _execCmd({cwd,command}){
    return new Promise((resolve,reject)=>{
        const exec = require('child_process').exec;
        exec(command,  {
            cwd,
        },(error, stdout, stderr) => {
            if (error) {
                console.error(`exec error: ${error}`);
                reject(error);
                return;
            }else{
                resolve();
            }
            console.log(`stdout: ${stdout}`);
            console.log(`stderr: ${stderr}`);
        });
    })
}

/**
 * 把webpack打包生成的组件 按NS移动到相应的目录s中去..
 * @param widgetInfo
    {
    jsFilePath:"",
    cssFilePath:"",
    widgetName:"",
    widgetNameSpace:"",
    }
 */
function * mvFile(widgetInfo,{workBench,env,watchMode}){

    let func = fse.move;
    if (watchMode) {
        func = fse.copy;
    }

    // console.log('mvFile', widgetInfo);
    let jsFilePath = path.join(workBench, './dist/barBuild', widgetInfo.jsFilePath);
    let cssFilePath = path.join(workBench, './dist/barBuild', widgetInfo.cssFilePath);
    let jsProxyFilePath = path.join(workBench, './dist/barBuild', widgetInfo.jsProxyFilePath);
    let widgetPath = path.join(workBench, './dist/barRepo', widgetInfo.widgetNameSpace);

    //copy
    func(jsProxyFilePath, widgetPath + "-p.js", {clobber: true}, function (err) {
        if (err) {
            console.error('-p.js',err)
            console.dir(widgetInfo);
            return;
        }
    });

    func(jsFilePath, widgetPath + ".js", {clobber: true}, function (err) {
        if (err) {
            console.error('.js',err)
            console.dir(widgetInfo);
            return;
        }
    });

    func(cssFilePath, widgetPath + ".css", {clobber: true}, function (err) {
        if (err) {
            return;
        }
    });


    let results = yield [isFileReadAble(jsProxyFilePath), isFileReadAble(jsFilePath), isFileReadAble(cssFilePath)];
    widgetInfo.jsProxyFilePath = results[0] ? widgetInfo.widgetNameSpace + "-p.js" : "";
    widgetInfo.jsFilePath = results[1] ? widgetInfo.widgetNameSpace + ".js" : "";
    widgetInfo.cssFilePath = results[2] ? widgetInfo.widgetNameSpace + ".css" : "";
}


/**
 * 文件 是否可读 , 如果文件不存在 , 也当做不可读
 * @param filePath
 * @return {Promise}
 */
function isFileReadAble(filePath){
    return new Promise((resolve,reject)=>{
        //兼容windows  .
        fs.access(filePath, (fs.R_OK || (fs.constants && fs.constants.R_OK)), (err) => {
            if(err){
                resolve(false);
            }else  {
                resolve(true);
            }
        });
    })
}